/*
Makefile的作用：自动化编译
	1.如果工程没有被编译过，那么工程中的所有.c文件都要被编译并且链接成可执行程序。
	2.如果工程中只有个别C文件被修改了，那么只编译这些被修改的C文件即可。
	3.如果工程的头文件被修改了，那么需要编译所有引用这个头文件的C文件，并且链接成可执行文件。

一条规则的语法格式：目标集，依赖集，命令列表
	目标: 依赖文件集合....
		命令         //命令列表中的每条命令必须以TAB键开始，不能使用空格。
		命令
		命令....     //规则中的命令集
		
	目的：更新或者生成目标。
	方法：先更新依赖文件然后再更新目标文件。更新就是执行规则中的命令列表。
	
make命令的执行过程：
	1.在当前目录下查找以Makefile命名的文件
	2.找到Makefile文件后，按照文件中定义的规则去编译生成最终的目标文件。
	*更新触发条件：目标文件不存在/目标依赖文件比目标文件新(通过比较修改时间)
	*更新方法：通过执行相应规则的命令列表，先更新依赖文件再更新目标文件。
	
终极目标：
	Makefile的执行就是为了生成这个目标
	终极目标的确定：1.输入make命令时指定的目标，例如 make clean
					2.没有指定目标时，默认为Makefile文件中第一个规则的目标
					*除了终极目标所在的规则外，其它规则的顺序在Makefile中是没有意义的。
		
*/

#示例1：
main:main.o sub1.o sub2.o  //生成终极目标的依赖文件集
	gcc -o main main.o sub1.o sub2.o      //链接.o文件生成最终可执行文件
main.o:
	gcc -c main.c    //只编译不连接，生成各个依赖文件
sub1.o:
	gcc -c sub1.c
sub2.o:
	gcc -c sub2.c
	
clean:
	rm *.o
	rm main



/*
makefile中的变量：
	makefile中的变量都是字符串
	变量的引用方法：$(变量名)
	
	变量的赋值：=   :=   ?=  +=
		 =  ：变量的真实值取决于它所引用的变量的最后一次有效值
		:=  : 变量的真实值取决于它所引用的变量的当前值
		?=  : 变量如果未被赋值则对其赋值，变量如果之前已被赋值则保持原来的值不变
		+=  ：给已经定义好的变量追加字符串(添加字符串时自动添加一个空格)
*/

#示例2.1
objects = main.o sub1.o sub2.o
main: $(objects)
	gcc -o main $(objects)

#示例2.2
name = zzk
curname1 := $(name)   #
curname2 = $(name)
curname3 ?= $(name)
curname4 += $(name)   #因为是第一个字符串，不添加空格。
curname4 += zzk       #不是第一个字符串，添加空格。 
name = kzz

print:
	@echo curname1:$(curname1)   #: curname1:zzk
	@echo curname2:$(curname2)   #: curname2:kzz
	@echo curname3:$(curname3)   #: curname3:kzz
	@echo curname4:$(curname4)   #: curname4:kzz zzk
	
	
	
/*
目的：一个命令完成从不同的依赖文件生成相应的目标。
方法：模式规则搭配自动化变量

模式规则：在规则的目标定义中要包含'%'，'%'表示长度任意的非空字符串。
		  目标中的'%'的值决定了依赖目标中的'%'的值
		  *先确定目标中的'%'的值，从而确定对应的依赖目标文件，再执行相应的规则命令集。

自动化变量：这种变量会把模式中所定义的一系列文件自动挨个取出
			$@:规则中的目标文件集
			$<:符合模式的一系列的文件集
*/
#示例3
output : a.o b.o
	gcc -o output a.o b.o
	
%.o : %.c  //将要更新的目标文件和此模式进行匹配，命中后则使用此规则生成该目标文件
	gcc -c $(<) -o $(@) //一个依赖目标文件($<)对应一个目标文件($@)
	
clean:
	rm a.o b.o output
	
该makefile的执行过程：
#	gcc -c a.c -o a.o
#	gcc -c b.c -o b.o
#	gcc -o output a.o b.o



/*
伪目标：目的不是生成相应的目标文件，而是执行规则下的命令集。


*/

#示例4
clean:  //该目标不依赖任何文件。使用make命令时指明目标如make clean，由于目标不存在所以会执行规则下的命令进行更新。
	rm -f *.o
#该用法的缺点：如果工作目录下存在同名的实际文件，则由于没有依赖项所以文件是最新的，因此规则下的命令不会被执行

#示例4.1
.PHONY : clean  //声明clean目标为伪目标
clean:
	rm -f *.o
#该用法的优点：声明clean为伪目标后，不管当前目录下是否存在名为clean的文件，输入make clean后规则后的命令都会被执行。

















